home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / develop™ Technical Journal / develop Issue 24 code / Scriptable Database 1.0a11.sea / Scriptable Database 1.0a11 / Base / Int64.cp / Int64.cp
Encoding:
Text File  |  1995-10-18  |  5.6 KB  |  235 lines  |  [TEXT/MPCC]

  1. /*
  2.     File:        Int64.c
  3.  
  4.     Contains:    64-bit math class
  5.  
  6.     Written by:    Dave Owens, tweeked by Andy Nicholas and Chris Bingham
  7.  
  8.     Copyright:    © 1994-1995 by Apple Computer, Inc., all rights reserved.
  9.  
  10.          <3>     3/20/95    andy    
  11. */
  12.  
  13. #ifdef MWTRACEBACKTABLES
  14. #pragma traceback on
  15. #endif
  16.  
  17. #include "Int64.h"
  18.  
  19. #pragma segment LookupSizes
  20.  
  21. //========================================================================================
  22. // CLASS Int64
  23. //========================================================================================
  24.  
  25. //----------------------------------------------------------------------------------------
  26. // Int64::IntuitOtherOperand: 
  27. //
  28. // IntuitOtherOperand
  29. //
  30. // This function decodes the input data and makes sure that it is packaged into
  31. // an Int64.
  32. //----------------------------------------------------------------------------------------
  33. const Int64* Int64::IntuitOtherOperand(short operation, const void* input, Int64* otherStorage)
  34.     {
  35.     int type = operation & typeMask;
  36.     if (type == typeOtherIsInt64)
  37.         return (const Int64*) input;
  38.  
  39.     otherStorage->fHigh32 = 0;
  40.  
  41.     switch (type)
  42.         {
  43.         case typeOtherIsInt:
  44.             {
  45.             if (*(const int*)input < 0)
  46.                 otherStorage->fHigh32 =  -1;
  47.                 
  48.             otherStorage->fLow32 = *(const int*) input;
  49.             break;
  50.             }
  51.         case typeOtherIsLong:
  52.             {
  53.             if (*(const long*)input < 0)
  54.                 otherStorage->fHigh32 =  -1;
  55.                 
  56.             otherStorage->fLow32 = *(const unsigned long*) input;
  57.             break;
  58.             }
  59.         
  60.         default:
  61.             otherStorage->fLow32 = *(const unsigned long*) input;
  62.         }
  63.         
  64.     return otherStorage;
  65.     } // Int64::IntuitOtherOperand 
  66.  
  67.  
  68. //----------------------------------------------------------------------------------------
  69. // Int64::Operation: 
  70. //----------------------------------------------------------------------------------------
  71. Int64 Int64::Operation(short operation, const void* input) const
  72.     {
  73.     Int64 sourceStorage;
  74.  
  75.     Int64 main;
  76.     main.fHigh32 = fHigh32;
  77.     main.fLow32  = fLow32;
  78.  
  79.     const Int64* other = IntuitOtherOperand(operation, input, &sourceStorage);
  80.     unsigned long temp;
  81.         
  82.     switch (operation & verbMask)
  83.         {
  84.         case verbAssign:
  85.             {
  86.             main.fHigh32 = other->fHigh32;
  87.             main.fLow32 = other->fLow32;
  88.             }
  89.             break;
  90.             
  91.         case verbAdd:
  92.             {
  93.             temp = main.fLow32 + other->fLow32;
  94.             if ((temp < main.fLow32) && (temp < other->fLow32))
  95.                 ++main.fHigh32;                        // catch overflow
  96.             main.fLow32 = temp;
  97.             main.fHigh32 += other->fHigh32;    
  98.             }
  99.             break;
  100.  
  101.         case verbSubtract:
  102.             {
  103.             if (other->fLow32 > main.fLow32)        // catch underflow
  104.                 --main.fHigh32;
  105.             main.fLow32 -= other->fLow32;
  106.             main.fHigh32 -= other->fHigh32;
  107.             }
  108.             break;
  109.  
  110.         //
  111.         // ••• this code needs to be replaced by something that works,
  112.         //        preferably a call to the 64-bit math library!
  113.         //
  114.         case verbMultiply:
  115.             {
  116.             if ((main == Int64(0L) ) || (*other == Int64(0L) ))
  117.                 main = 0;
  118.             else
  119.                 {
  120.                 // assumes a maximum multiply of 48 bits * 31 bits
  121.                 unsigned short a3 = (main.fHigh32 & 0xFFFF);
  122.                 unsigned short a2 = (main.fLow32 & 0xFFFF0000) >> 16;
  123.                 unsigned short a1 = (main.fLow32 & 0xFFFF);
  124.                 unsigned short b2 = (other->fLow32 & 0xFFFF0000) >> 16;
  125.                 unsigned short b1 = (other->fLow32 & 0xFFFF);
  126.                 
  127.                 main = (unsigned long) ((a3 * b2));
  128.                 main <<= 16;
  129.                 main += (unsigned long) ((a3 * b1) + (a2 * b2));
  130.                 main <<= 16;
  131.                 main += (unsigned long) ((a2 * b1) + (a1 * b2));
  132.                 main <<= 16;
  133.                 main += (unsigned long)(a1 * b1);
  134.                 }
  135.             }
  136.             break;
  137.  
  138.         //
  139.         // ••• this code needs to be replaced by something that works,
  140.         //        preferably a call to the 64-bit math library!
  141.         //
  142.         case verbDivide:
  143.             {
  144.             if ((main == Int64(0L) ) || (*other == Int64(0L) ))
  145.                 main = 0;
  146.             else
  147.                 {
  148. //                other->fLow32 is the denominator
  149.                 long numerator = main.fHigh32;
  150.                 Int64 times;
  151.                 times.fHigh32 = numerator / other->fLow32;
  152.                 
  153.                 numerator -= times.fHigh32 * other->fLow32;
  154.                 numerator = (numerator << 16) | (main.fLow32 >> 16);
  155.                 times.fLow32 = numerator / other->fLow32;
  156.     
  157.                 numerator -= times.fLow32 * other->fLow32;
  158.                 numerator = (numerator << 16) | (main.fLow32 & 0xFFFF);
  159.                 times.fLow32 <<= 16;
  160.                 times.fLow32 += numerator / other->fLow32;
  161.  
  162.                 main.fHigh32 = times.fHigh32;
  163.                 main.fLow32 = times.fLow32;
  164.                 }
  165.             }
  166.             break;
  167.  
  168.         case verbShiftRight:
  169.             {
  170. //            ASSERT(*other < 64);
  171.             temp = other->fLow32;
  172.             main.fLow32 =  (main.fHigh32 << (32 - temp)) | (main.fLow32 >> temp);
  173.             main.fHigh32 = main.fHigh32 >> temp;
  174.             }
  175.             break;
  176.  
  177.         case verbShiftLeft:
  178.             {
  179. //            ASSERT(*other < 64);
  180.             temp = other->fLow32;
  181.             main.fHigh32 = (main.fHigh32 << temp) | (main.fLow32 >> (32 - temp));
  182.             main.fLow32 = main.fLow32 << temp;
  183.             }
  184.             break;
  185.  
  186.         default:
  187. //            ASSERT(false);
  188.             break;
  189.         }
  190.         
  191.     return main;
  192.     }
  193.  
  194. //----------------------------------------------------------------------------------------
  195. // Int64::Comparison: 
  196. //----------------------------------------------------------------------------------------
  197. Boolean    Int64::Comparison(short comparison, const void* input) const
  198.     {
  199.     Int64 otherStorage;
  200.  
  201.     const Int64* other = IntuitOtherOperand(comparison, input, &otherStorage);
  202.     Boolean result = false;
  203.     Boolean negateResult = false;
  204.     
  205.     switch (comparison & cmpMask)
  206.         {
  207.         case cmpNotEqual:
  208.             negateResult = true;
  209.         case cmpEqual:
  210.             result = (fHigh32 == other->fHigh32) && (fLow32 == other->fLow32);
  211.             break;
  212.         
  213.         case cmpGreaterOrEqual:
  214.             negateResult = true;
  215.         case cmpLess:
  216.             result = (fHigh32 < other->fHigh32) ||
  217.                     ((fHigh32 == other->fHigh32) && (fLow32 < other->fLow32));
  218.             break;
  219.  
  220.         case cmpLessOrEqual:
  221.             negateResult = true;
  222.         case cmpGreater:
  223.             result = (fHigh32 > other->fHigh32) ||
  224.                     ((fHigh32 == other->fHigh32) && (fLow32 > other->fLow32));
  225.             break;
  226.             
  227.         default:
  228. //            ASSERT(false);
  229.             break;
  230.         }
  231.     
  232.     return result ^ negateResult;
  233.     } // Int64::Comparison 
  234.  
  235.